import { _decorator, Component, Node, Asset, director } from 'cc';
import { IS2CMessageObj } from './MessageInc';
const { ccclass, property } = _decorator;

let requestIdBase = 1;
let lastHandledReq = 0;
const requestMap = {};
const errTimeout = { errcode: -1, errmsg: 'timeout' };
const errOK = { errcode: 0, errmsg: 'ok' };

@ccclass
export default class NetWork {
    // websocket 连接地址
    public static wssLink: string = "ws://127.0.0.1:8002";
    //public static wssLink: string = "ws://192.168.0.101:8002";
    // public static wssLink: string = "ws://172.16.68.160:8002";
    // public static wssLink: string = "ws://192.168.52.170:8002";
    // public static wssLink: string = "ws://172.16.68.135:8002";

    public static _wsiSendBinary: WebSocket;

    private static _handlers = [];

    public static addHandler(handler: any) {
        this._handlers.push(handler);
    }

    public static removeHandler(handler: any) {
        let idx = this._handlers.indexOf(handler);
        if (idx != -1) {
            this._handlers.splice(idx, 1);
        }
    }

    public static initNetWorkListen(wsObj: WebSocket) {

        wsObj.onmessage = (event) => {
            let msgObj: IS2CMessageObj = JSON.parse(event.data);
            if (msgObj.data) {
                msgObj.data = JSON.parse(msgObj.data)
            }

            let requestId = msgObj.rid;
            if (requestId) {
                this.handleRequestResult(requestId, msgObj.err || errOK, msgObj.data);
            }
            else {
                console.log(`s2c: ${msgObj.cmd}`, msgObj.data);
                for (let i = 0; i < this._handlers.length; ++i) {
                    let handler = this._handlers[i];
                    let func = handler['onNet_' + msgObj.cmd] as Function;
                    if (func) {
                        func.apply(handler, [msgObj.data]);
                    }
                }
            }
        }
    }

    public static connectToWsserver = function (cb?: Function) {
        this._wsiSendBinary = new WebSocket(this.wssLink, []);
        this.initNetWorkListen(this._wsiSendBinary);
        this._wsiSendBinary.onopen = function () {
            console.log("[Connection Server Succes]", true);
            if (cb instanceof Function) {
                cb();
            }
        };

        this._wsiSendBinary.onclose = () => {
            director.emit('net_close');
        };
    }

    public static sendDataToServer(command: string, data?: Object, cb?: Function, target?: any, timeout: number = 5000) {
        // console.log(`c2s: ${command} , ${data}`);

        let requestId = requestIdBase++;
        let msgObj = {
            "cmd": command,
            "data": JSON.stringify(data)
        }
        if (cb) {
            msgObj['rid'] = requestId;
            requestMap[requestId] = { cb: cb, target: target };
            setTimeout(() => {
                this.handleRequestResult(requestId, errTimeout, null);
            }, timeout);
        }
        this._wsiSendBinary.send(JSON.stringify(msgObj));
    }

    public static async sendDataToServerSync(command: string, data?: Object, timeout: number = 5000):Promise<{ err: any, data: any }> {
        return new Promise((resolve, reject) => {
            NetWork.sendDataToServer(command, data, (err, data) => {
                resolve({ err, data });
            }, null, timeout);
        });
    }

    private static handleRequestResult(requestId, err, data) {
        let req = requestMap[requestId];
        if (req) {
            req.cb.apply(req.target, [err, data]);
        }

        //delete all out-dated request.
        for (let i = lastHandledReq; i <= requestId; ++i) {
            let reqId = i;
            delete requestMap[reqId];
        }
        lastHandledReq = requestId;
    }
}